using System.Linq;
using data.contracts;
using NUnit.Framework;

namespace generator.tests
{
    [TestFixture]
    public class BoardSyntaxTests
    {
        [Test]
        public void Pins_are_distinct() {
            var pins = BoardSyntax.Pins(new[] {
                new Wire("a.out", "", "b.in"),
                new Wire("b.out", "", "c.in"),
                new Wire("c.out", "", "d.in"),
            });
            Assert.That(pins.Select(x => x.Board).ToArray(), Is.EquivalentTo(new[] {"a", "b", "c", "d"}));
        }

        [Test]
        public void Pins_includes_this() {
            var pins = BoardSyntax.Pins(new[] {
                new Wire("this.in", "", "a.in")
            });
            Assert.That(pins.Select(x => x.Board).ToArray(), Is.EquivalentTo(new[] {"this", "a"}));
        }

        [Test]
        public void Pins_with_board_namespace() {
            var pins = BoardSyntax.Pins(new[] {
                new Wire("n1.n2.n3.a.in", "", "n4.n5.b.out")
            });
            Assert.That(pins.Select(x => x.Board).ToArray(), Is.EquivalentTo(new[] {"n1.n2.n3.a", "n4.n5.b"}));
            Assert.That(pins.Select(x => x.Name).ToArray(), Is.EquivalentTo(new[] {"in", "out"}));
            Assert.That(pins.Select(x => x.Type).ToArray(), Is.EquivalentTo(new[] {"", ""}));
        }

        [Test]
        public void Pins_with_type_namespace() {
            var pins = BoardSyntax.Pins(new[] {
                new Wire("(ebcbauteile.IJoin) join.Input", "", "b.out")
            });
            Assert.That(pins.Select(x => x.Board).ToArray(), Is.EquivalentTo(new[] {"join", "b"}));
            Assert.That(pins.Select(x => x.Name).ToArray(), Is.EquivalentTo(new[] {"Input", "out"}));
            Assert.That(pins.Select(x => x.Type).ToArray(), Is.EquivalentTo(new[] {"ebcbauteile.IJoin", ""}));
        }

        [Test]
        public void Pins_include_special_names() {
            var pins = BoardSyntax.Pins(new[] {
                new Wire("this.in", "", "$split1.Input"),
                new Wire("$split1.Output1", "", "a.out"),
                new Wire("$split1.Output2", "", "b.out"),
            });
            Assert.That(pins.Select(x => x.Board).ToArray(), Is.EquivalentTo(new[] {"this", "$split1", "a", "b"}));
        }

        [Test]
        public void Star_in_type_is_shortcut_for_IEnumerable() {
            Assert.That(BoardSyntax.ParsedType("   int  *  "), Is.EqualTo("IEnumerable<int>"));
        }

        [Test]
        public void Empty_type_is_accepted() {
            Assert.That(BoardSyntax.ParsedType(""), Is.EqualTo(""));
        }
    }
}